<template>
  <div class="ue-upload-file">
    <div class="vuf-drop-area"
         @click="handleClick"
         @dragleave="handleDragLeave"
         @dragover="handleDragOver"
         @dragenter="handleDragEnter"
         @drop="handleDrop">
      <i class="vuf-icon1" v-show="loading != 1">
        <i class="vuf-icon1-arrow"></i>
        <i class="vuf-icon1-body"></i>
        <i class="vuf-icon1-bottom"></i>
      </i>
      <span class="vuf-hint" v-show="loading !== 1">{{ lang.hint }}</span>
      <span class="vuf-loading" v-show="loading === 1">{{ lang.loading }}</span>
      <div class="vuf-progress-wrap" v-show="loading === 1">
        <span class="vuf-progress" :style="progressStyle"></span>
      </div>
      <span class="vuf-no-supported-hint" v-show="!isSupported">{{ lang.noSupported }}</span>
      <input type="file" v-show="false" @change="handleChange" ref="fileinput">
    </div>
    <div class="vuf-error" v-show="hasError">
      <i class="vuf-icon2"></i>
      {{ errorMsg }}
    </div>
    <div class="vuf-success" v-show="loading === 2">
      <i class="vuf-icon3"></i>
      {{ lang.success }}
    </div>
  </div>
</template>

<script>
  'use strict';
  export default {
    name: "ueUpload",
    props: {
      // 域，上传文件name，触发事件会带上（如果一个页面多个图片上传控件，可以做区分
      scope: {
        type: String,
        'default': 'upload'
      },
      // 显示该控件与否
      isShow: {
        'default': true
      },
      // 上传服务地址
      action: {
        type: String,
        'default': ''
      },
      // 其他要上传文件附带的数据，对象格式
      params: {
        type: Object,
        'default': {}
      },
      // 单文件大小限制 单位kb
      maxSize: {
        type: Number,
        'default': 2048
      },
      // 上传文件类型 数据类型字符串 如：|xls|xlsx|sheet|vnd.openxmlformats-officedocument.spreadsheetml.sheet|
      fileType: {
        'default': null
      },
      // 是否多文件上传，默认 false 单文件上传
      multiFile: {
        'default': false
      }
    },
    data () {
      let isSupported = true,
        lang = {
          hint: '点击，或将文件拖动至此处',
          loading: '正在上传……',
          noSupported: '浏览器不支持该功能，请使用IE10以上或其他现代浏览器！',
          success: '上传成功',
          fail: '上传失败',
          error: {
            multiFile: '仅限单文件上传',
            outOfSize: '单文件大小超限 ',
          }
        };
      if (typeof FormData != 'function') {
        isSupported = false;
      }
      return {
        loading: 0, //0未开始 1上传中 2成功 3错误
        lang,
        isSupported,
        hasError: false,
        files: '',
        progress: 0,
        errorMsg: ''
      }
    },
    computed: {
      progressStyle () {
        let {progress} = this;
        return {
          width: progress + '%'
        }
      }
    },
    watch: {
      'isShow': function (newValue) {
        if (newValue) {
          this.reset();
        }
      }
    },
    methods: {
      handleDragLeave (e) {
        e.preventDefault();
      },
      handleDrop (e) {
        e.preventDefault();
        if (this.loading !== 1) {
          let files = e.dataTransfer.files;
          this.reset();
          if (this.checkFiles(files)) {
            this.upload(files);
          }
        }
      },
      handleDragEnter (e) {
        e.preventDefault();
      },
      handleDragOver (e) {
        e.preventDefault();
      },
      handleClick (e) {
        if (this.loading !== 1) {
          if (e.target !== this.$refs.fileinput) {
            e.preventDefault();
            this.$refs.fileinput.click();
          }
        }
      },
      handleChange (e) {
        if (this.loading !== 1) {
          let files = e.target.files;
          this.reset();
          if (this.checkFiles(files)) {
            this.upload(files);
          }
        }
      },
      checkFiles (files) {
        let that = this,
          {lang, maxSize, fileType, multiFile} = that,
          fileNum = files.length;
        // 是否文件为空
        if (fileNum < 1) {
          this.$Notice.info({
            title: '温馨提醒',
            desc: lang.error.multiFile
          });
          return false;
        }
        if (!fileType) {
          return true;
        }
        let fileType_ = ('|' + fileType.join("|") + '|').replace('xlsx', "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 仅限单文件？
        if (!multiFile) {
          if (fileNum > 1) {
            this.$Notice.error({
              title: '文件数量超限',
              desc: lang.error.multiFile
            });
            return false;
          }
          // 仅限支持配置文件类型范围类文件
          let file = files[0];
          let _fileType = file.type;
          if (!_fileType) {
            _fileType = file.name.substr(file.name.indexOf(".") + 1)
          }
          console.log(_fileType);
          var type = '|' + _fileType + '|';
          if (fileType_ && fileType_.indexOf(type) < 0) {
            this.$Notice.error({
              title: '文件类型错误',
              desc: '仅限支持' + fileType.join(',') + '格式文件'
            });
            return false;
          }

          // 超出大小
          let maxSizeM = file.size / 1024;
          if (maxSizeM > maxSize) {
            this.$Notice.error({
              title: '文件超限',
              desc: lang.error.outOfSize + "[实际：" + Math.round(maxSizeM, 2) + "KB, 限制：" + maxSize + "KB]"
            });
            return false;
          }

        } else {
          for (let i = 0; i < fileNum; i++) {
            // 仅限支持文件类型
            let file = files[0];
            let _fileType = file.type;
            if (!_fileType) {
              _fileType = file.name.substr(file.name.indexOf(".") + 1)
            }
            var type = '|' + _fileType + '|';
            if (fileType_ && fileType_.indexOf(type) < 0) {
              this.$Notice.error({
                title: '文件类型错误',
                desc: '仅限支持' + fileType.join(',') + '格式文件'
              });
              return false;
            }
            // 超出大小
            let maxSizeM = file.size / 1024;
            if (maxSizeM > maxSize) {
              this.$Notice.error({
                title: '文件超限',
                desc: lang.error.outOfSize + "[实际：" + Math.round(maxSizeM, 2) + "KB, 限制：" + maxSize + "KB]"
              });
              return false;
            }
          }
        }
        return true;
      },
      reset () {
        let that = this;
        that.loading = 0;
        that.hasError = false;
        that.errorMsg = '';
        that.progress = 0;
      },
      upload (files) {
        let that = this,
          {action, params, multiFile, scope, lang} = this,
          fmData = new FormData();
        // 判断是否单文件
        if (!multiFile) {
          fmData.append(scope, files[0]);
        } else {
          fmData.append(scope, files);
        }
        // 添加其他参数
        if (typeof params == 'object' && params) {
          Object.keys(params).forEach((k) => {
            fmData.append(k, params[k]);
          })
        }
        // 监听进度回调
        const uploadProgress = function (event) {
          if (event.lengthComputable) {
            that.progress = 100 * Math.round(event.loaded) / event.total;
          }
        };
        // 上传文件
        that.loading = 1;
        new Promise(function (resolve, reject) {
          let client = new XMLHttpRequest();
          client.open('POST', action, true);
          client.onreadystatechange = function () {
            if (this.readyState !== 4) {
              return;
            }
            if (this.status === 200) {
              resolve(this.responseText);
            } else {
              reject(this.responseText);
            }
          };
          client.upload.addEventListener("progress", uploadProgress, false); //监听进度
          client.send(fmData);
        }).then(
          // 上传成功
          function (resData) {
            that.files = '';
            that.loading = 0;
            that.$Notice.success({
              title: '上传结果',
              desc: '文件已上传成功'
            });
          },
          // 上传失败
          function (resData) {
            console.log(resData);
            that.loading = 0;
            that.files = '';
            let message = "文件上传失败";
            if (resData && resData['message']) {
              message = resData['message'];
            }
            that.$Notice.error({
              title: '上传结果',
              desc: message
            });
          }
        );
      }
    }
  }
</script>

<style lang="sass" scoped>@import "./css/upload.css"</style>
